Imports System.Drawing
Imports System.Data

Partial Class SizeE
    Inherits System.Web.UI.Page

    Private Const Q As String = Chr(34)

    Private moServer As SQLAutoDocLib.Server = Nothing
    Private moDatabase As SQLAutoDocLib.Database = Nothing
    Private moOwner As SQLAutoDocLib.Login = Nothing
    Private moTable As SQLAutoDocLib.Table = Nothing

    Private moChart As jChart.GraphChart

    Private Enum ViewMode As Integer
        TableDetail = 1
        TableSizeChart = 2
        DatabaseSizeChart = 3
    End Enum

    Private mlMode As ViewMode

    Private msDBID As String
    Private msTBID As String
    Private msWeek As String

    Private moData As DataTable = Nothing

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        msDBID = Request.QueryString("D")
        msTBID = Request.QueryString("T")
        msWeek = Request.QueryString("W")

        moDatabase = New SQLAutoDocLib.Database(msDBID)
        moDatabase.Load()

        moServer = New SQLAutoDocLib.Server(moDatabase.ServerID)
        moServer.Load()

        If msTBID > "" Then
            moTable = New SQLAutoDocLib.Table(msTBID)
            moTable.Load()

            moOwner = New SQLAutoDocLib.Login(moTable.OwnerID)
            moOwner.Load()
        End If

        Dim oFactory As New SQLAutoDocLib.TableSize_Factory

        If IsDate(msWeek) _
                AndAlso IsNumeric(msDBID) _
                AndAlso IsNumeric(msTBID) Then
            '---Show trends for table
            mlMode = ViewMode.TableSizeChart

            divZoom.Visible = True
            AZoom.HRef = "SQSizeE.aspx?D=" & moDatabase.ID & "&W=" & HttpUtility.UrlEncode(msWeek)
            ARefresh.HRef = "SQSizeE.aspx?D=" & moDatabase.ID & "&W=" & HttpUtility.UrlEncode(msWeek) & "&T=" & msTBID

            '---Get Data
            moData = oFactory.AverageWeeklyTableSize(12, msTBID, msWeek)

            MakeTableSizeChart()

        ElseIf IsDate(msWeek) _
                AndAlso IsNumeric(msDBID) Then
            '---Show table average sizes for specific week
            mlMode = ViewMode.TableDetail

            divZoom.Visible = True
            AZoom.HRef = "SQSizeE.aspx?S=" & moDatabase.ServerID & "&D=" & moDatabase.ID
            ARefresh.HRef = "SQSizeE.aspx?D=" & moDatabase.ID & "&W=" & HttpUtility.UrlEncode(msWeek)
            tdCaption.InnerText = "SQLAutoDoc Average Table Sizes ending " & msWeek

            '---Get Data
            moData = oFactory.TableAverageSizesForWeek(CDate(msWeek).AddDays(7), msDBID)

        ElseIf IsNumeric(msDBID) Then
            '---Show database size trends
            mlMode = ViewMode.DatabaseSizeChart

            divZoom.Visible = False
            ARefresh.HRef = "SQSizeE.aspx?S=" & moDatabase.ServerID & "&D=" & moDatabase.ID

            '---Get Data
            moData = oFactory.AverageWeeklyDatabaseSize(12, msDBID)

            MakeDatabaseSizeChart()
        End If
    End Sub

    Protected Sub ShowBody()
        If mlMode = ViewMode.TableDetail Then
            ShowTableSizeDetail()
        Else
            ShowImageTag()
        End If
    End Sub

    Private Function MakeImageMapString() As String
        Dim sImageMap As String = ""

        '---The GetAllRegions function of the Chart object gets all regions
        '   of all series of all overlays, in order of display.
        For Each oRegion As jChart.RegionArea In moChart.RegionList
            Dim sCoords As String = ""

            '---The SeriesPoints property of the RegionArea object gives
            '   us the coordinates we need to describe a polygon around each
            '   series data point.
            Dim oPoints As Point() = oRegion.SeriesPoints
            sCoords = oPoints(0).X & "," & oPoints(0).Y

            For iPoint As Integer = 1 To oPoints.GetUpperBound(0)
                sCoords = sCoords & "," & oPoints(iPoint).X & "," & oPoints(iPoint).Y
            Next

            '---Now that we have the polygon, let's tell the web browser what 
            '   to do when our user clicks on a data point. Here we'll just display
            '   a javascript message, but anything is possible...
            Dim sArea As String = "<area " & _
                                        " shape=" & Chr(34) & "poly" & Chr(34) & _
                                        " coords=" & Chr(34) & sCoords & Chr(34)

            Dim lXValue As Long = oRegion.XValue
            Dim lYValue As Long = oRegion.YValue

            Dim oRow As DataRow = moData.Rows(lXValue)

            Select Case mlMode
                Case ViewMode.TableDetail

                Case ViewMode.DatabaseSizeChart
                    sArea = sArea & " href=" & Q & "SQSizeE.aspx?D=" & msDBID & "&W=" & oRow.Item("dtWeekDate") & Q
            End Select

            sArea = sArea & " title=" & Q & FormatSize(oRegion.YValue) & Q & _
                             " alt=" & Q & oRegion.SeriesName & Q & _
                             " value=" & Q & oRegion.YValue & Q & ">" & _
                                        vbCrLf


            sImageMap = sImageMap & sArea
        Next

        Return sImageMap
    End Function

    Private Sub MakeDatabaseSizeChart()
        '---Let's set up the chart.
        '   We'll make it 600 pixels wide by 400 pixels high.        
        moChart = New jChart.GraphChart(510, 460)
        moChart.ChartName = "Database Size - Last 12 weeks"

        '---We'll specify a 10 pixel border all the way around the inside
        '   edge of the chart.
        moChart.ChartDimensions.FrameSize = 10

        '---The Y Axis column on the left will be 20 pixels wide.
        moChart.ChartDimensions.YAxis1LabelColumnWidth = 20

        '---The X Axis row on the bottom will be 20 pixels high.
        moChart.ChartDimensions.XAxisLabelRowHeight = 20

        '---Let's add the X Axis values
        '   We'll have 7 values and in place of the numeric values we'll
        '   display friendly labels.
        Dim lCount As Integer = moData.Rows.Count
        Dim lMax As Long = 0

        Dim oXAxisValues(lCount - 1) As Single
        Dim oXAxisLabels(lCount - 1) As String
        Dim oSeriesValues(lCount - 1) As Single
        Dim oYAxisLabels(5) As String

        For i As Integer = 0 To lCount - 1
            oXAxisValues(i) = i
            oXAxisLabels(i) = moData.Rows(i).Item("dtWeekDate")

            If IsNumeric(moData.Rows(i).Item("AvgSize")) Then
                oSeriesValues(i) = moData.Rows(i).Item("AvgSize")

                If moData.Rows(i).Item("AvgSize") > lMax Then
                    lMax = moData.Rows(i).Item("AvgSize")
                End If
            Else
                oSeriesValues(i) = -999
            End If
        Next

        For i As Integer = 0 To 5
            oYAxisLabels(i) = FormatSize((lMax / 5) * i)
        Next

        '---We'll create an XAxis object using the ChartDimensions object
        '   from the chart we just created.
        Dim oXAxis As New jChart.XAxis(moChart.ChartDimensions, oXAxisValues)

        '---Let's tell the X Axis about the friendly labels to display in place
        '   of numbers.
        oXAxis.XAxisLabels = oXAxisLabels
        oXAxis.FontAngle = jChart.XAxis.Rotation.Diagonal

        '---OK, finally let's tell the chart about its X Axis.
        moChart.XAxis = oXAxis

        '---Now, let's set up the Y Axis.
        Dim oYAxis1 As New jChart.YAxis(jChart.YAxis.Alignment.Left, moChart.ChartDimensions, 5, 0, lMax)
        oYAxis1.YAxisLabels = oYAxisLabels

        '---Now let's tell the chart about our Y Axis 
        moChart.YAxis1 = oYAxis1

        '---Now that we have values, we'll need a series
        '   Our series will be a line series.
        Dim oIndicator As New jChart.Indicator( _
                    jChart.Indicator.Type.Cross, _
                    Color.Green, _
                    15)

        Dim oLineSeries As New jChart.Overlay.Series.LineSeries(oIndicator)
        With oLineSeries
            '---We will call our series "series one". 
            '   This value is accessible on drill-down from the image map.
            .Name = "Database Size"

            '---Now we'll give the series the values it should use.
            .Values = oSeriesValues

            '---The series will be green in color
            .Color = Color.Green

            '---The series will be slightly transparent (75% opaque)
            .Opacity = 0.75

            .LineType = Drawing2D.DashStyle.Solid
        End With

        '---Since we are using a line chart, which belongs to the 
        '   LineOverlay overlay type, we'll need a LineOverlay object.
        Dim oLineOverlay As jChart.Overlay.LineOverlay

        '---We need to tell the overlay which dimensions and axes to use when
        '   we create it.
        oLineOverlay = New jChart.Overlay.LineOverlay(moChart.ChartDimensions, oXAxis, oYAxis1)

        '---Let's add the series to the overlay
        oLineOverlay.Series.Add(oLineSeries)

        '---Let's add the overlay to the chart.
        moChart.OverLays.Add(oLineOverlay)

        '---OK. All done. Now let's draw the chart.
        '   We'll start by creating a bitmap onto which the chart will be drawn.
        '   We do it this way so that the bitmap can be shared (a background image
        '   perhaps?)
        Dim oPicture As New Bitmap( _
                moChart.ChartDimensions.OuterWidth, _
                moChart.ChartDimensions.OuterHeight, _
                System.Drawing.Imaging.PixelFormat.Format24bppRgb)

        '---Now that we've created the bitmap, we'll draw the chart on it and save it
        '   to a temporary location on the server in JPEG format. The charting object
        '   creates a unique filename for our new chart. This unique filename is
        '   accessible via the chart's FileName property (see ImageURL)

        '---The path where the image will be saved must have write access for the ASPNET
        '   process enabled.
        moChart.SaveChartToFile( _
                    Application("TempPath"), _
                    System.Drawing.Imaging.ImageFormat.Jpeg)

    End Sub

    Private Sub MakeTableSizeChart()
        Dim oTable As New SQLAutoDocLib.Table(msTBID)
        oTable.Load()

        Dim sChartName As String = oTable.Name & " Size, Last 12 weeks"
        tdCaption.InnerText = "SQLAutoDoc Table Trends for " & oTable.Name

        '---Let's set up the chart.
        '   We'll make it 600 pixels wide by 400 pixels high.        
        moChart = New jChart.GraphChart(510, 460)
        moChart.ChartName = sChartName

        '---We'll specify a 10 pixel border all the way around the inside
        '   edge of the chart.
        moChart.ChartDimensions.FrameSize = 10

        '---The Y Axis column on the left will be 20 pixels wide.
        moChart.ChartDimensions.YAxis1LabelColumnWidth = 20

        '---The X Axis row on the bottom will be 20 pixels high.
        moChart.ChartDimensions.XAxisLabelRowHeight = 20

        '---Let's add the X Axis values
        '   We'll have 7 values and in place of the numeric values we'll
        '   display friendly labels.
        Dim lCount As Integer = moData.Rows.Count
        Dim lMax As Long = 1

        Dim oXAxisValues(lCount - 1) As Single
        Dim oXAxisLabels(lCount - 1) As String
        Dim oSeriesValues(lCount - 1) As Single

        For i As Integer = 0 To lCount - 1
            oXAxisValues(i) = i
            oXAxisLabels(i) = moData.Rows(i).Item("dtWeekDate")

            If IsNumeric(moData.Rows(i).Item("AvgSize")) Then
                oSeriesValues(i) = moData.Rows(i).Item("AvgSize")

                If moData.Rows(i).Item("AvgSize") > lMax Then
                    lMax = moData.Rows(i).Item("AvgSize")
                End If
            Else
                oSeriesValues(i) = -999
            End If
        Next

        '---We'll create an XAxis object using the ChartDimensions object
        '   from the chart we just created.
        Dim oXAxis As New jChart.XAxis(moChart.ChartDimensions, oXAxisValues)

        '---Let's tell the X Axis about the friendly labels to display in place
        '   of numbers.
        oXAxis.XAxisLabels = oXAxisLabels
        oXAxis.FontAngle = jChart.XAxis.Rotation.Diagonal

        '---OK, finally let's tell the chart about its X Axis.
        moChart.XAxis = oXAxis

        '---Now, let's set up the Y Axis.
        Dim oYAxis1 As New jChart.YAxis(jChart.YAxis.Alignment.Left, moChart.ChartDimensions, 5, 0, lMax)

        '---Now let's tell the chart about our Y Axis 
        moChart.YAxis1 = oYAxis1

        '---Now that we have values, we'll need a series
        '   Our series will be a line series.
        Dim oIndicator As New jChart.Indicator( _
                    jChart.Indicator.Type.Cross, _
                    Color.Green, _
                    15)

        Dim oLineSeries As New jChart.Overlay.Series.LineSeries(oIndicator)
        With oLineSeries
            '---We will call our series "series one". 
            '   This value is accessible on drill-down from the image map.
            .Name = "Table Size"

            '---Now we'll give the series the values it should use.
            .Values = oSeriesValues

            '---The series will be green in color
            .Color = Color.Green

            '---The series will be slightly transparent (75% opaque)
            .Opacity = 0.75

            .LineType = Drawing2D.DashStyle.Solid
        End With

        '---Since we are using a line chart, which belongs to the 
        '   LineOverlay overlay type, we'll need a LineOverlay object.
        Dim oLineOverlay As jChart.Overlay.LineOverlay

        '---We need to tell the overlay which dimensions and axes to use when
        '   we create it.
        oLineOverlay = New jChart.Overlay.LineOverlay(moChart.ChartDimensions, oXAxis, oYAxis1)

        '---Let's add the series to the overlay
        oLineOverlay.Series.Add(oLineSeries)

        '---Let's add the overlay to the chart.
        moChart.OverLays.Add(oLineOverlay)

        '---OK. All done. Now let's draw the chart.
        '   We'll start by creating a bitmap onto which the chart will be drawn.
        '   We do it this way so that the bitmap can be shared (a background image
        '   perhaps?)
        Dim oPicture As New Bitmap( _
                moChart.ChartDimensions.OuterWidth, _
                moChart.ChartDimensions.OuterHeight, _
                System.Drawing.Imaging.PixelFormat.Format24bppRgb)

        '---Now that we've created the bitmap, we'll draw the chart on it and save it
        '   to a temporary location on the server in JPEG format. The charting object
        '   creates a unique filename for our new chart. This unique filename is
        '   accessible via the chart's FileName property (see ImageURL)

        '---The path where the image will be saved must have write access for the ASPNET
        '   process enabled.
        moChart.SaveChartToFile( _
                    Application("TempPath"), _
                    System.Drawing.Imaging.ImageFormat.Jpeg)
    End Sub

    Private Sub ShowTableSizeDetail()
        HttpContext.Current.Response.Write("<table class=" & Q & "wmObjectSize_T" & Q & " style=" & Q & "width: 515px;" & Q & ">")

        HttpContext.Current.Response.Write("<tr class=" & Q & "wmObjectSize_TH" & Q & " style=" & Q & "background-color: #C3C4C1;" & Q & ">")

        HttpContext.Current.Response.Write("<td class=" & Q & "wmObjectSize_ZN" & Q & ">")
        HttpContext.Current.Response.Write("Name")
        HttpContext.Current.Response.Write("</td>")

        HttpContext.Current.Response.Write("<td class=" & Q & "wmObjectSize_ZS" & Q & " colspan=" & Q & "2" & Q & ">")
        HttpContext.Current.Response.Write("Size")
        HttpContext.Current.Response.Write("</td>")

        HttpContext.Current.Response.Write("</tr>")

        Dim bAlternatingRow As Boolean = False

        For Each oRow As DataRow In moData.Rows
            If bAlternatingRow = False Then
                HttpContext.Current.Response.Write("<tr class=" & Q & "wmObjectSize_T" & Q & ">")
            Else
                HttpContext.Current.Response.Write("<tr class=" & Q & "wmObjectSize_TA" & Q & ">")
            End If
            Response.Write("<td>")

            Response.Write("<a href=" & Q & "SQSizeE.aspx?D=" & msDBID & _
                                                    "&T=" & oRow.Item("TableID") & _
                                                    "&W=" & HttpUtility.UrlEncode(msWeek) & Q & ">")

            Response.Write(oRow.Item("Name"))
            Response.Write("</a>")

            Response.Write("</td>")

            Response.Write("<td class=" & Q & "wmObjectSize_IZS" & Q & ">")
            Response.Write("<img src=" & MakeTableString_Size(oRow, bAlternatingRow) & " border=" & Q & "0" & Q & "/>")
            Response.Write("</td>")

            Response.Write("<td class=" & Q & "wmObjectSize_IZS" & Q & ">")
            Response.Write(FormatSize(oRow.Item("P10_AvgSize")))
            Response.Write("</td>")

            Response.Write("</tr>")

            bAlternatingRow = Not bAlternatingRow
        Next
        Response.Write("</table>")
    End Sub

    Private Function MakeTableString_Size(ByVal oRow As DataRow, ByVal bAlternatingRow As Boolean) As String
        Dim oURL As New StringBuilder

        If bAlternatingRow = True Then
            oURL.Append("ilc.aspx?T=L&W=60&H=20&TH=2&FG=5959FF&BG=FFFFCC")
        Else
            oURL.Append("ilc.aspx?T=L&W=60&H=20&TH=2&FG=5959FF&BG=FFFFFF")
        End If

        For i As Integer = 1 To 10
            oURL.Append("&DP=" & oRow.Item("P" & i & "_AvgSize"))
        Next

        Return oURL.ToString
    End Function

    Private Sub ShowImageTag()
        If Not moChart Is Nothing Then
            Dim sHTM As String = "<img src=" & Q & Session("TempURL") & moChart.FileName & Q & " alt=" & Q & Q & " usemap=" & Q & "#MyMap" & Q & " />"

            sHTM = sHTM & "<map id=" & Q & "Map1" & Q & " name=" & Q & "MyMap" & Q & ">"
            sHTM = sHTM & MakeImageMapString()
            sHTM = sHTM & "</map>"

            Response.Write(sHTM)
        End If
    End Sub

    Protected Function FormLabel() As String
        Dim oFactory As New SQLAutoDocLib.ScanHistory_Factory
        Dim sCurrentScan As String = ""
        Dim sLastScan As String = ""
        oFactory.GetTimeOfLastScan(moDatabase.ID, SQLAutoDocLib.ScanSchedule.Type.SizeScan, "SQLAutoDocLib.TableSize", sCurrentScan, sLastScan)

        Dim sValue As String = ""

        Select Case mlMode
            Case ViewMode.DatabaseSizeChart
                sValue = "Database Size Trends for " & moDatabase.Name & " last scan completed " & sLastScan

            Case ViewMode.TableDetail
                sValue = "Database Size Detail for " & moDatabase.Name & " for w/b " & msWeek & " last scan completed " & sLastScan

            Case ViewMode.TableSizeChart
                sValue = "Table Size Trends for " & moDatabase.Name & "." & moOwner.Login & "." & moTable.Name & " last scan completed " & sLastScan
        End Select

        If sCurrentScan > "" Then
            sValue = " scan in progress started " & sCurrentScan
        End If

        Return sValue
    End Function

    Protected Function ScanMode() As String
        Return "Size"
    End Function

    Protected Function EditMode() As String
        Return "Size"
    End Function

    Protected Function ServerID() As String
        Return moServer.ID
    End Function

    Private Function FormatSize(ByVal oValue As Object) As String
        Dim sResult As String = ""

        Dim lSize As Long = 0

        If Not oValue Is System.DBNull.Value Then
            lSize = Val(oValue)
        End If

        Dim sSize As String = ""
        If lSize = 0 Then
            sSize = "0 kb"

        ElseIf lSize < 2500 Then
            sSize = FormatNumber(lSize, 0, 0, 0, TriState.True) & " kb"

        ElseIf lSize < 1050000 Then
            sSize = FormatNumber(lSize / 1024, 0, 0, 0, TriState.True) & " mb"

        Else
            sSize = FormatNumber((lSize / 1024) / 1024, 0, 0, 0, TriState.True) & " gb"

        End If

        Return sSize
    End Function

End Class
